// File:    defs.h
// Author:  sqbang
// Purpose: report error for ExprEval
//------------------------------------------------------------------------------

//declaration header
#include "COMMON/expr/error.h"

namespace ExprEval
{

ErrorInfo::ErrorInfo():
    m_stop_when_numeric_limits_reached (true)
{}



void ErrorInfo::add_error(const int code, const std::string& location)
{
    ErrorCode ERROR_CODE;
    if(code == 0)
    {
        ERROR_CODE = GOOD;
    }
    else if(code == EDOM)
    {
        ERROR_CODE = ERROR_DOMAIN;
    }
    else if(code == ERANGE)
    {
        ERROR_CODE = ERROR_RANGE;
    }
    else
    {
        ERROR_CODE = INVALID_VALUE;
    }

    m_errors.push_back(std::make_pair (ERROR_CODE, location));
}



void ErrorInfo::setStopWhenNumericLimitsReached (const bool stop)
{
    m_stop_when_numeric_limits_reached = stop;
}



void ErrorInfo::check_error(const std::string& expr) const
{
    std::stringstream oss;
    bool stop = false;
    for (unsigned int ie = 0; ie < m_errors.size(); ++ie)
    {
        switch(m_errors[ie].first)
        {
        case GOOD:
            {
                break;
            }
        case ERROR_DOMAIN:
            {
                oss << "when evaluate expression of \"" <<expr<< "\"\n";
                oss << "variable out of domain of the function \"" << m_errors[ie].second << "\"" << std::endl;
                SHOW_NONFATAL_ERROR(oss.str());

                if(m_stop_when_numeric_limits_reached)
                {
                    stop = true;
                }
                break;
            }
        case ERROR_RANGE:
            {
                oss << "when evaluate expression of \"" << expr << "\"\n";
                oss << "result is too large to represent as a double of function \"" << m_errors[ie].second << "\"" << std::endl;
                SHOW_NONFATAL_ERROR(oss.str());

                if(m_stop_when_numeric_limits_reached)
                {
                    stop = true;
                }
                break;
            }
        default:
            {
                SHOW_FATAL_ERROR("unknown errro");
            }
        }
    }

    if(stop)
    {
        SHOW_FATAL_ERROR("stopped while evaluate expression.");
    }
}

}
